"""
a1:  区间值模糊数 格式为([],[])

self.q: q值
self.x: 一个参数时所用的变量

a2:     区间值模糊数 格式为([],[])

编写时间:2022/7/3 14:37
编写人:操祉豪
参考文献:区间值广义正交模糊 Choquet 积分算子及群决策方法
"""

from Utilities.AutoGetOperator.selectPackage import get_func

Operator_IVQ_ROFS=get_func(r'Operators/OperationOperators/OperatorIVQROF.py','Operator_IVQ_ROFS')




class Choquet(Operator_IVQ_ROFS):
    def __init__(self, data_list=[], weight_list=[], q=3, x=2, a=2, b=2):
        '''
        对一些数据进行初始化
        n: data_list的长度
        x_list: 存放所有排列组合情况用二进制表示，比如有x5, x2, x1则用二进制10011来表示，可以转换成唯一的十进制表示
        :return:
        '''
        super().__init__(data_list, weight_list, q, x, a, b)
        self.n = len(self.data_list)
        self.x_list = []
        self.x_list.append(0)
        for i in range(1, 2 ** self.n):
            cnt = 0
            while i > 0:
                if i & 1 == 1:
                    cnt += 1
                i = i >> 1
            self.x_list.append(1 / (self.n + 1 - cnt))
        self.x_list = [0, 0.4, 0.4, 0.3, 0.3, 0.8, 0.8, 1]  #测试数据

    def B(self, i):
        '''
        求u(Bi)的对应x_list的值
        :param i: B的下标
        :return:
        '''
        res = 0
        data_list = self.sortdata()
        for k in range(i):
            res = res + (1 << (data_list[k][1] - 1))

        return res

    def sortdata(self):
        """
            function : 根据模糊数得分排列,并记录远标号顺序
            a        : 一个模糊集, 形式:（[x,y]，[x,y]）
            return   : PWA 集结后的数据结果，形式：[（[x,y]，[x,y]）, index]
        """
        s_list = [[self.getsco(ai, self.q).getScore(), ai, k] for ai, k in zip(self.data_list, range(1, len(self.data_list) + 1))]
        s_list.sort(key=lambda x: x[0], reverse=True)

        return [[ai[1], ai[2]] for ai in s_list]


class ChoquetA(Choquet):

    def getResult(self):

        data_list = self.sortdata()
        res = self.kmulti(data_list[0][0], self.x_list[self.B(1)] - self.x_list[self.B(0)])
        for i in range(2, self.n + 1):
            res = self.add(self.kmulti(data_list[i - 1][0], self.x_list[self.B(i)] - self.x_list[self.B(i - 1)]), res)


        return res

class ChoquetGA(Choquet):

    def getResult(self):

        data_list = self.sortdata()
        res = self.pow(data_list[0][0], self.x_list[self.B(1)] - self.x_list[self.B(0)])
        for i in range(2, self.n + 1):
            res = self.multi(self.pow(data_list[i - 1][0], self.x_list[self.B(i)] - self.x_list[self.B(i - 1)]), res)

        return res


if __name__ == '__main__':
    # data_list = [([0.31, 0.24], [0.73, 0.72]), ([0.97, 0.12], [0.12, 0.05]),
    #              ([0.8, 0.52], [0.73, 0.15]), ([0.91, 0.49], [0.42, 0.47]), ([0.95, 0.06], [0.19, 0.1])]
    data_list = [([0.7,0.9],[0.3,0.5]), ([0.3,0.4],[0.5,0.6]), ([0.5,0.6],[0.4,0.5])]
    weight_list = [0.1, 0.2, 0.3, 0.1, 0.3],
    # Pa = A(data_list)
    Pa = ChoquetA(data_list, q = 3)
    # Pa = WA(data_list,weight_list)
    # Pa = WGA(data_list,weight_list)
    # Pa = OWA(data_list,weight_list)
    print(Pa.getResult())

